package gui;

import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import evolutionaryProblems.Problem;
import flatlandAgent.FlatlandParameters;
import javax.swing.JTextArea;

public class GUI extends JFrame {
	
	private static final long serialVersionUID = 1L;
	private Problem problem;
	private FlatlandParameters parameters;
	private JPanel contentPane;
	private LineChart lineChart;
	private JPanel panel;
	private JLabel lblEvolving;
	private JTextField nofChildren;
	private JTextField nofAdults;
	private JTextField nofGenerations;
	private JTextField crossoverRate;
	private JTextField mutationRate;
	private JTextField elitism;
	private JSplitPane splitPane;
	private JLabel lblSimulationSpeed;
	private JLabel lblFood;
	private JLabel lblPoison;
	private JLabel lblHiddenLayers;
	private JSlider slider;
	private JTextField foodDist;
	private JTextField poisonDist;
	private JTextField layers;
	private JRadioButton rdbtnStatic;
	private JRadioButton rdbtnDynamic;
	private final ButtonGroup buttonGroup = new ButtonGroup();
	private JToggleButton tglbtnPause;
	private JButton btnStart;
	private JButton btnResetSimulation;

	public GUI(Problem problem, FlatlandParameters parameters) {
		init(problem, parameters);
	}

	private void init(Problem problem, FlatlandParameters parameters) {
		this.problem = problem;
		this.parameters = parameters;
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 1060, 812);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		splitPane = new JSplitPane();
		splitPane.setBounds(0, 232, 1039, 531);
		splitPane.setDividerLocation(500);
		splitPane.setRightComponent(null);
		contentPane.add(splitPane);
		
		lineChart = new LineChart();
		lineChart.setVisible(true);
		splitPane.setLeftComponent(lineChart);
		
		JTextArea textArea = new JTextArea();
		lineChart.add(textArea);
		
		panel = new JPanel();
		panel.setBounds(0, 0, 1039, 229);
		contentPane.add(panel);
		panel.setLayout(null);
		
		lblEvolving = new JLabel("<html><u>Evolving Neural Networks</u></html>");
		lblEvolving.setBounds(366, 5, 306, 29);
		lblEvolving.setFont(new Font("Arial Black", Font.BOLD, 20));
		panel.add(lblEvolving);
		
		JLabel lblNewLabel = new JLabel("nof children");
		lblNewLabel.setBounds(39, 84, 86, 20);
		panel.add(lblNewLabel);
		
		JLabel lblNumberOfAdults = new JLabel("nof adults");
		lblNumberOfAdults.setBounds(39, 109, 86, 20);
		panel.add(lblNumberOfAdults);
		
		JLabel lblMutationRate = new JLabel("Mutation rate");
		lblMutationRate.setBounds(249, 109, 91, 20);
		panel.add(lblMutationRate);
		
		JLabel lblCrossoverRate = new JLabel("Crossover rate");
		lblCrossoverRate.setBounds(249, 84, 91, 20);
		panel.add(lblCrossoverRate);
		
		JLabel lblNumberOfGenerations = new JLabel("nof generations");
		lblNumberOfGenerations.setBounds(39, 134, 100, 20);
		panel.add(lblNumberOfGenerations);
		
		JLabel lblSettings = new JLabel("Settings");
		lblSettings.setFont(new Font("Arial Black", Font.PLAIN, 15));
		lblSettings.setBounds(269, 51, 71, 22);
		panel.add(lblSettings);
		
		nofChildren = new JTextField();
		nofChildren.setBounds(142, 84, 86, 20);
		panel.add(nofChildren);
		nofChildren.setColumns(10);
		
		nofAdults = new JTextField();
		nofAdults.setBounds(142, 109, 86, 20);
		panel.add(nofAdults);
		nofAdults.setColumns(10);
		
		nofGenerations = new JTextField();
		nofGenerations.setBounds(142, 134, 86, 20);
		panel.add(nofGenerations);
		nofGenerations.setColumns(10);
		
		crossoverRate = new JTextField();
		crossoverRate.setBounds(345, 84, 86, 20);
		panel.add(crossoverRate);
		crossoverRate.setColumns(10);
		
		mutationRate = new JTextField();
		mutationRate.setBounds(345, 109, 86, 20);
		panel.add(mutationRate);
		mutationRate.setColumns(10);
		
		tglbtnPause = new JToggleButton("Pause simulation");
		tglbtnPause.addActionListener(new PauseSimulation());
		tglbtnPause.setBounds(835, 137, 121, 23);
		panel.add(tglbtnPause);
		
		btnStart = new JButton("Start simulation");
		btnStart.addActionListener(new StartSimulation());
		btnStart.setBounds(835, 102, 121, 23);
		panel.add(btnStart);
		
		btnResetSimulation = new JButton("Reset simulation");
		btnResetSimulation.addActionListener(new RestartSimulation()); 
		btnResetSimulation.setBounds(835, 174, 121, 23);
		panel.add(btnResetSimulation);
		
		JLabel lblFunctionality = new JLabel("Functionality");
		lblFunctionality.setFont(new Font("Arial Black", Font.PLAIN, 15));
		lblFunctionality.setBounds(841, 69, 121, 22);
		panel.add(lblFunctionality);
		
		JLabel lblElitism = new JLabel("Elitism");
		lblElitism.setBounds(249, 134, 46, 20);
		panel.add(lblElitism);
		
		elitism = new JTextField();
		elitism.setBounds(345, 134, 86, 20);
		panel.add(elitism);
		elitism.setColumns(10);
		
		lblSimulationSpeed = new JLabel("Simulation speed");
		lblSimulationSpeed.setBounds(454, 174, 109, 20);
		panel.add(lblSimulationSpeed);
		
		lblFood = new JLabel("Food");
		lblFood.setBounds(454, 84, 37, 20);
		panel.add(lblFood);
		
		lblPoison = new JLabel("Poison");
		lblPoison.setBounds(550, 84, 52, 20);
		panel.add(lblPoison);
		
		lblHiddenLayers = new JLabel("Hidden layers");
		lblHiddenLayers.setBounds(454, 109, 71, 20);
		panel.add(lblHiddenLayers);
		
		slider = new JSlider(JSlider.HORIZONTAL, 0, 1000, 500);
		slider.addChangeListener(new SliderListener());
		slider.setMajorTickSpacing(200);
		slider.setMinorTickSpacing(100);
		slider.setPaintTicks(true);
		slider.setPaintLabels(true);
		slider.setBounds(550, 167, 200, 45);
		slider.setValue(0); 
		panel.add(slider);
		
		foodDist = new JTextField();
		foodDist.setColumns(10);
		foodDist.setBounds(494, 84, 46, 20);
		panel.add(foodDist);
		
		poisonDist = new JTextField();
		poisonDist.setColumns(10);
		poisonDist.setBounds(600, 84, 46, 20);
		panel.add(poisonDist);
		
		layers = new JTextField();
		layers.setColumns(10);
		layers.setBounds(550, 109, 96, 20);
		panel.add(layers);
		
		rdbtnStatic = new JRadioButton("Static");
		buttonGroup.add(rdbtnStatic);
		rdbtnStatic.setBounds(454, 137, 71, 23);
		panel.add(rdbtnStatic);
		
		rdbtnDynamic = new JRadioButton("Dynamic");
		buttonGroup.add(rdbtnDynamic);
		rdbtnDynamic.setBounds(550, 137, 96, 23);
		panel.add(rdbtnDynamic);
	}
	
	@Override
	public Container getContentPane() {
		return this.contentPane;
	}
	
	public void addMaxFit(int x, double y) {
		lineChart.addMaxFit(x, y);
	}
	
	public void addAverageFit(int x, double y) {
		lineChart.addAverageFit(x, y);
	}
	
	public void addStandardDeviation(int x, double y) {
		lineChart.addStandardDeviation(x, y);
	}
	
	public void setMap(JPanel jPanel) {
		splitPane.setRightComponent(jPanel);
	}
	
	private void readParameters(){
		parameters.setElitims(Integer.parseInt(this.elitism.getText()));
		parameters.setMutationRate(Double.parseDouble(this.mutationRate.getText())); 
		parameters.setCrossoverRate(Double.parseDouble(this.crossoverRate.getText())); 
		parameters.setNumOfChildenToBeGenerated(Integer.parseInt(this.nofChildren.getText())); 
		parameters.setPopulationSize(Integer.parseInt(this.nofAdults.getText())); 
		parameters.setMaxNumberOfIterations(Integer.parseInt(this.nofGenerations.getText()));
		parameters.setFoodDist(Double.parseDouble(foodDist.getText()));
		parameters.setPoisonDist(Double.parseDouble(poisonDist.getText()));
		if (rdbtnDynamic.isSelected()) parameters.setDynamicMap(true);
		else parameters.setDynamicMap(false);
		parameters.setNetworkLayout(setLayers());
	}
	
	public void showDefaultParameters(){
		this.elitism.setText(Integer.toString(parameters.getElitism())); 
		this.mutationRate.setText(Double.toString(parameters.getMutationRate())); 
		this.crossoverRate.setText(Double.toString(parameters.getCrossoverRate())); 
		this.nofChildren.setText(Integer.toString(parameters.getNumOfChildenToBeGenerated())); 
		this.nofAdults.setText(Integer.toString(parameters.getPopulationSize())); 
		this.nofGenerations.setText(Integer.toString(1000));
		this.poisonDist.setText(Double.toString(parameters.getPoisonDist()));
		this.foodDist.setText(Double.toString(parameters.getFoodDist()));
		if (parameters.isDynamicMap()) this.rdbtnDynamic.setSelected(true);
		else this.rdbtnStatic.setSelected(true);
		this.layers.setText(getHiddenLayers());
	}
	
	private String getHiddenLayers() {
		String s = "";
		int[] layout = parameters.getNetworkLayout();
		
		if (layout.length == 2)
			return "";
		
		for (int i = 1; i < layout.length-1; i++) {
			s += Integer.toString(layout[i])+ ",";
		}
		s = s.substring(0, s.length()-1);
		return s;
	}
	
	private int[] setLayers() {
		String input = layers.getText().replaceAll("\\s", "");
		String returnString = "";
		
		if (input.length() == 0)
			returnString = "6,3";
		else returnString = "6," + input + "," + "3";

		String[] layersString = returnString.split(",");
		int[] layersInt = new int[layersString.length];
		for (int i = 0; i < layersString.length; i++) {
			if (! layersString[i].equals("") )
					layersInt[i] = Integer.parseInt(layersString[i]);
		}
		System.out.println("Setlayers:" + Arrays.toString(layersInt));
		return layersInt;
	}
	
	class StartSimulation implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			readParameters(); 
			problem.startSimulation();
			((JButton) e.getSource()).setEnabled(false);
		}
		
	}
	
	class PauseSimulation implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			JToggleButton btn = (JToggleButton) arg0.getSource();
			if (btn.isSelected()) {
				btn.setText("Continue simulation");
				problem.pauseSimulation();
			}
			else {
				problem.continueSimulation();
				btn.setText("Pause simulation");
			}
		}
		
	}
	
	class RestartSimulation implements ActionListener {
		

		@Override
		public void actionPerformed(ActionEvent arg0) {
			problem.killSimulation(); 
			lineChart.emptyDataSet();
			getContentPane().removeAll(); 
			init(problem, parameters);
			showDefaultParameters();
			btnStart.setEnabled(true); 
			revalidate();
			repaint(); 
		}
	}
	
	class SliderListener implements ChangeListener {

		@Override
		public void stateChanged(ChangeEvent e) {
			parameters.setTimePerFrame(slider.getValue());
			if (slider.getValue() == 0)
				parameters.setViewMap(false);
			else parameters.setViewMap(true);
		}
		
	}
}
